<?php
/**
 * イベントマップ
 */
require_once 'Google/Calendar2.php';
require_once 'Toodledo/api/Toodledo.php';

/**
 * イベントマップクラス
 * @author admin
 *
 */
class Models_EventmappController
{
	/** 最終同期日時保存ファイル */
	protected $_pathLastModifyDatetime;
	/** イベントマップ保存ファイル */
	protected $_pathEventMap;
	/**  最終同期日時 */
	protected $_lastModefyDatetime;
	/** カレンダーオブジェクト */
	protected $_Calendar;
	/** カレンダーイベントリスト */
	protected $_calendarEventList;
	/** Todoオブジェクト */
	protected $_Task;
	/** Todoイベントリスト　*/
	protected $_taskEventList;
	/** マップ情報保存ファイル */
	protected $_pathMapInfo;
	/** マップ情報 */
	protected $_mapInfoText;
	/** 更新中タスクIDリスト */
	protected $_updatingTaskIdList = array();
	/** 状態コード */
	protected $_conditionCode = -1;
	/** ユーザーハッシュ */
	protected $_userHash;

	/** 状態コード：カレンダーログインエラー */
	const VALUE_CONDITIONCODE_LOGIN_ERROR_CALENDAR = '1';
	/** 状態コード：タスクログインエラー */
	const VALUE_CONDITIONCODE_LOGIN_ERRROR_TASK = '2';
	/** 状態コード：指定カレンダーが存在しない */
	const VALUE_CONDITIONCODE_NOCALENDATNAME = '3';
	/** 状態コード：カレンダーイベント取得エラー */
	const VALUE_CONDITIONCODE_CALENDAR_EVENT_GET_ERROR = '4';
	/** 状態コード：タスクイベント取得エラー */
	const VALUE_CONDITIONCODE_TASK_EVENT_GET_EEROR = '5';
	/** 状態コード：カレンダーイベント追加エラー */
	const VALUE_CODITIONCODE_CALENDAR_EVENT_ADD_ERROR = '6';
	/** 状態コード：タスクイベント追加エラー */
	const VALUE_CONDITIONCODE_TASK_EVENT_ADD_ERROR = '7';
	/** 状態コード：カレンダーイベント変更エラー */
	const VALUE_CONDITIONCODE_CALENDER_EVENT_UPDATE_ERROR = '8';
	/** 状態コード：タスクイベント変更エラー */
	const VALUE_CONDITIONCODE_TASK_EVENT_UPDATE_ERROR = '9';
	/** 状態コード：同期開始時刻決定  */
	const VALUE_CONDITIONCODE_DISIDE_SYNCDATETIME = '10';

	/**
	 * コンストラクタ
	 * @param _Task $cUser
	 * @param _Task $cPass
	 * @param _Task $tUser
	 * @param _Task $tPass
	 * @param _Task $calendarName
	 * @param _Task $appId
	 */
	public function __construct($cUser, $cPass, $tUser, $tPass, $calendarName, $appId)
	{
		/*** カレンダーオブジェクトインスタンス */
		$this->_Calendar = new Google_Calender($cUser, $cPass);
		/*** Todoオブジェクトインスタンス */
		$this->_Task = new Toodledo($tUser, $tPass, $appId);
		/*** エラー判定 */
		if ($this->_Task->exeptionMessage != '') {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_LOGIN_ERRROR_TASK;
			return;
		}

		/*** ユーザーハッシュコードを生成する */
		$cUser = $this->_Calendar->カレンダーのIDを返す($this->_Calendar->プライマリカレンダーのインデックスを返す());
		$this->_userHash = self::createUserHash($cUser, $cPass);

		/*** データフォルダー存在判定 */
		if (!file_exists(dirname(__FILE__) . '/eventmap/databox')) {
			mkdir(dirname(__FILE__) . '/eventmap/databox');
		}

		/*** マップ情報を読み込む */
		$this->_loadMapInfo();
		/*** 最終同期日時取得 */
		$this->_lastModefyDatetime = $this->getLastModifyDatetime();
		/*** 最終同期日時以降のに更新されたカレンダーイベント取得 */
		$ret = $this->_setCalendarEvents($cUser, $cPass, $this->_lastModefyDatetime, $calendarName);
		/*** エラーなら中断 */
		if ($ret === FALSE) {
			return;
		}
		/** カレンダーイベントリスト操作 */
		$ret = $this->_calendarEventListProc();
		/*** エラーなら中断 */
		if ($ret === FALSE) {
			return;
		}

		/*** Todo用最終更新日時編集 */
		$todoUpdateted = strtotime($this->_lastModefyDatetime);
		/*** 最終更新日以降に更新されたTodoイベント取得 */
		$ret = $this->_setTaskEvents($tUser, $tPass, $appId, $todoUpdateted);
		/*** エラーなら中断 */
		if ($ret === FALSE) {
			return;
		}
		/*** Todoイベントリスト操作 */
		$this->_taskEventListProc();

		/*** マップ情報更新 */
		file_put_contents($this->_pathEventMap, implode("\n", $this->_mapInfoText));
		/*** 最終同期日時更新 */
		$this->saveLastModifyDatetime();
	}

	/**
	 * toodledo ＡＰＩのアプリケーションＩＤを返す
	 * @return boolean|Ambigous <>
	 */
	static public function getAppIdToodledo()
	{
		/***
		 * MAGIC WORD BLOCK
		 */
		$fileName = dirname(__FILE__) . '/eventmap/appid.php';
		$keyDataStart = '/*start-data';
		$keyDataEnd = 'end -data*/';
		$keyToodledoApiKey = 'toodlede-appid';

		/*** FILE CHECK */
		if (!file_exists($fileName)) {
			return FALSE;
		}
		/*** FILE OPEN */
		$text = file($fileName, FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
		/*** SEARCH START END INDEX */
		$startIndex = array_search($keyDataStart, $text);
		/*** エラー判定 */
		if ($startIndex === FALSE) {
			return FALSE;
		}
		$endIndex = array_search($keyDataEnd, $text);
		/*** エラー判定 */
		if ($endIndex === FALSE) {
			return FALSE;
		}
		$i = $startIndex;
		/*** SEARCH APPID */
		while ($i < $endIndex) {
			$divide = explode(',', $text[$i]);
			/*** フォーマット判定 */
			if (count($divide) == 2) {
				/*** 発見 */
				if ($divide[0] == $keyToodledoApiKey) {
					return $divide[1];
				}
			}
			$i ++;
		}
		return FALSE;
	}

	/**
	 * UIDをハッシュ化する
	 * @param _Task $user
	 * @return string
	 */
	static public function createUserHash($user)
	{
		$result = md5($user);
		return $result;
	}

	/**
	 * タスクイベントリスト操作
	 */
	protected function _taskEventListProc()
	{
		$mapList = $this->_createMapInfoTaskEventKeyHash();
		/*** タスクを個別に全件同期する */
		foreach ($this->_taskEventList as $todoEvent) {
			$ret = $this->_taskEventProc($todoEvent, $mapList);
			/*** エラーなら中断 */
			if ($ret === FALSE) {
				return FALSE;
			}
		}
		return TRUE;
	}

	/**
	 * マップからタスクを削除する
	 * @param _Task $taskId
	 */
	protected function _deleteTaskFromMapList($taskId)
	{
		$countMapList = count($this->_mapInfoText);
		/*** マップ情報を全件捜査 */
		while ($i < $countMapList) {
			$divide = explode(',', $this->_mapInfoText[$i]);
			/*** フォーマット判定 */
			if (count($divide) < 2) {
				$i ++;
				continue;
			}
			/*** 該当タスクＩＤを削除する */
			if ($divide[1] == $taskId) {
				unset($this->_mapInfoText[$i]);
			}
			$i ++;
		}
	}

	/**
	 * Todoイベント（単体）操作
	 */
	protected function _taskEventProc($taskEvent, $mapList)
	{
		/*** 開始日が設定されていないタスクはカレンダーに登録しない */
		if ($taskEvent[ToodledoConstants::KEY_STARTDATE] == '') {
			return TRUE;
		}
		/*** タスクID取得 */
		$taskId = $taskEvent[ToodledoConstants::KEY_ID];
		/*** 完了タスクは終わる */
		if ($taskEvent[ToodledoConstants::KEY_COMPLETED] != '') {
			return TRUE;
		}
		/*** 処理中のタスクである場合 */
		if (array_search($taskId, $this->_updatingTaskIdList) !== FALSE) {
			return TRUE;
		}
		/*** 同期項目取得 */
		$name = $taskEvent[ToodledoConstants::KEY_TITLE];
		$content = $taskEvent[ToodledoConstants::KEY_NOTE];

		$恒久的URL = self::恒久的URLを作成する($taskId);
		if (!self::コンテンツに恒久的URLが含まれている場合TRUEを返す($content,$恒久的URL)){
		    $content = self::コンテンツに恒久的URLを追加する($content, $恒久的URL);
		}

		/*** 終日の場合 2013-11-24 20:00 */
		if ($taskEvent[ToodledoConstants::KEY_STARTTIME] == 0) {
			$unixStartTime = $taskEvent[ToodledoConstants::KEY_STARTDATE];
			$unixStartTime = $this->_Task->unixTimeFromDateAndTime(
					$taskEvent[ToodledoConstants::KEY_STARTDATE],
					'12:00 am');
			$startTime = date('Y-m-d', $unixStartTime);
			$endTime = '';
			$allDayFlg = TRUE;
		} else {
			/*** 終日でない場合 */
			$unixStartTime = $taskEvent[ToodledoConstants::KEY_STARTTIME];
			$unixStartTime = $this->_Task->unixTimeFromDateAndTime(
					$taskEvent[ToodledoConstants::KEY_STARTDATE],
					$taskEvent[ToodledoConstants::KEY_STARTTIME]);
			/*** 作業時間が未設定の場合 */
			if ($taskEvent[ToodledoConstants::KEY_LENGTH] == 0) {
				$unixEndTime = $unixStartTime + 1800;
			} else {
				$unixEndTime = $unixStartTime + $taskEvent[ToodledoConstants::KEY_LENGTH] * 60;
			}
			$startTime = Google_Calender::uTime2String($unixStartTime);
			$endTime = Google_Calender::uTime2String($unixEndTime);
			$allDayFlg = FALSE;
		}

		/*** マップリストにない（新規登録タスクイベント） */
		if (!isset($mapList[$taskId])) {
			/*** カレンダーイベント追加 */
			$calendarId = $this->addCalendarEvent($name, $content, $startTime, $endTime);
			/*** エラー判定 */
			if ($calendarId === FALSE) {
				$this->_conditionCode = self::VALUE_CODITIONCODE_CALENDAR_EVENT_ADD_ERROR;
				return FALSE;
			}
			$this->_mapInfoText[] = $calendarId . ',' . $taskId;
			return TRUE;
		}

		/*** カレンダーイベントＩＤをマップリストから取得する */
		$calendarId = $mapList[$taskId];
		/*** 取得したカレンダーイベントIDからカレンダーイベントを取得する */
		$targetEvent = $this->_Calendar->setTargetEvent($calendarId);
		/*** 取得失敗（手動削除想定）*/
		if ($targetEvent === FALSE) {
			/*** カレンダーイベント更新ではなく追加にする */
			$calendarId = $this->addCalendarEvent($name, $content, $startTime, $endTime);
			/*** エラー判定 */
			if ($calendarId === FALSE) {
				$this->_conditionCode = self::VALUE_CODITIONCODE_CALENDAR_EVENT_ADD_ERROR;
				return FALSE;
			}
			/*** マップリストＤＥＬＥＴＥ＆ＩＮＳＥＲＴ */
			$this->_deleteTaskFromMapList($taskId);
			$this->_mapInfoText[] = $calendarId . ',' . $taskId;
			return TRUE;
		}
		$uTimeCalendarUpdated = strtotime((string)$targetEvent->UPDATED);
		$uTimeTaskUpdated = $taskEvent[ToodledoConstants::KEY_MODIFIED];
		$uTimeTaskUpdated = strtotime($uTimeTaskUpdated) + 50400;
		/*** カレンダーの更新日時の方が新しい場合 */
		if ($uTimeCalendarUpdated > $uTimeTaskUpdated) {
			// 現状のままリターン
			return TRUE;
		}
		/*** カレンダーイベント更新 */
		$ret = $this->updateCalendarEvent($calendarId, $name, $content, $startTime, $endTime);
		return $ret;
	}

	const 恒久的URLプレフィックス = 'http://www.toodledo.com/tasks/index.php?x=1561031#task_%s';
	static public function 恒久的URLを作成する($タスクID)
	{
	    $result = sprintf(self::恒久的URLプレフィックス, $タスクID);
	    return $result;
	}
	static public function コンテンツに恒久的URLが含まれている場合TRUEを返す($コンテンツ, $恒久的URL)
	{
	    $result = false;
	    if (strpos($コンテンツ, $恒久的URL) !== FALSE) {
	        $result = TRUE;
	    }
	    return $result;
	}
	static public function コンテンツに恒久的URLを追加する($コンテンツ, $恒久的URL)
	{
	    $result = $恒久的URL . "\r\n" . $コンテンツ;
	    return $result;
	}

	protected function _addTaskLink($content, $taskId)
	{
	    $prefixTaskLink = "http://www.toodledo.com/tasks/index.php?x=1561031#task_";
	    $taskLink = $prefixTaskLink . $taskId;
	    if (strpos($content,$taskLink) === FALSE) {
	        $content = $taskLink . "\r\n" . $content;
	    }
	    return $content;
	}

	/**
	 * カレンダーイベントを更新する
	 * @param _Task $calendarId
	 * @param _Task $name
	 * @param _Task $content
	 * @param _Task $startTime
	 * @param _Task $endTime
	 * @return boolean
	 */
	public function updateCalendarEvent($calendarId, $name, $content, $startTime, $endTime) {
		/*** イベントが消えている場合は追加 */
		if ($this->_Calendar->getTargetEvent() === FALSE) {
			$this->_Calendar->setTargetEvent($calendarId);
		}
		/*** カレンダーイベント更新 */
		$ret = $this->_Calendar->updateEvent(
				$name,
				$content,
				$startTime,
				$endTime
		);
		return $ret;
	}

	/**
	 * カレンダーにイベントを追加する。
	 * @param _Task $name
	 * @param _Task $content
	 * @param _Task $startTime
	 * @param _Task $endTime
	 * @return string
	 */
	public function addCalendarEvent($name,$content,$startTime,$endTime)
	{
		/*** カレンダーイベント追加 */
		$calendarId = (string)$this->_Calendar->addEvent(
				$name,
				$content,
				$startTime,
				$endTime);
		return $calendarId;
	}

	/**
	 * カレンダーイベントリスト操作
	 */
	protected function _calendarEventListProc()
	{
		$mapList = $this->_createMapInfoCalendarEventKeyHash();
		/*** 個別同期を全件実施 */
		foreach ($this->_calendarEventList as $calendarEvent) {
			$ret = $this->_calendarEventProc($calendarEvent, $mapList);
			/*** エラー判定 */
			if ($ret === FALSE) {
				return FALSE;
			}
		}
		return TRUE;
	}

	/**
	 * カレンダーイベント（個別）操作
	 */
	protected function _calendarEventProc($calendarEvent, $mapList)
	{
		/*** 同期項目取得 */
		$calendarId = (string)$calendarEvent[Google_Calender::KEY_EVENT_ID];
		$name = (string)$calendarEvent[Google_Calender::KEY_EVENT_NAME];
		$content = (string)$calendarEvent[Google_Calender::KEY_EVENT_CONTENT];
		$startUTime = $calendarEvent[Google_Calender::KEY_EVENT_START_TIME];
		$startSTime = Toodledo::divideUnixTime2Time($startUTime);
		$length = Google_Calender::getTimeLength(
				$calendarEvent[Google_Calender::KEY_EVENT_START_TIME],
				$calendarEvent[Google_Calender::KEY_EVENT_END_TIME]);

		/*** マップリストにない（新規登録カレンダーイベント）の場合*/
		if (!isset($mapList[$calendarId])) {
			/*** Toodledoイベント追加 */
			$addedTaskId = $this->addTask($name, $content, $startUTime, $startSTime, $length, $calendarEvent['ALLDAY']);
			/*** エラー判定 */
			if ($addedTaskId === FALSE) {
				$this->_conditionCode = self::VALUE_CONDITIONCODE_TASK_EVENT_ADD_ERROR;
				file_put_contents(dirname(__FILE__).'/../../../tclog.html', 'EE:'.$name."<br />\n", FILE_APPEND);
				return FALSE;
			}
			/*** マップレコード追加 */
			$this->_mapInfoText[] = $calendarId . ',' . $addedTaskId;
			/*** 更新中タスクＩＤ追加 */
			$this->_updatingTaskIdList[] = $addedTaskId;

			$this->恒久的タスクURLを追加してカレンダーに書き戻す($addedTaskId, $calendarEvent);

// 完了
			return TRUE;
		}// 以降：マップリストにある場合

		/*** タスクIDをマップリストから取得する */
		$taskId = $mapList[$calendarId];
		/*** 取得したタスクIDからタスクイベントを取得する */
		$result = $this->_Task->request('getTasks',array(ToodledoConstants::KEY_ID=>$taskId), Toodledo::RAW);
		$event = Toodledo::xml2array($result);
		/*** 該当タスクがない（手動削除を想定）*/
		if ($event['total'] == 0) {
			/*** 更新ではなく追加にする */
			$addedTaskId = $this->addTask($name, $content, $startUTime, $startSTime, $length, $calendarEvent['ALLDAY']);
			/*** エラー判定 */
			if ($addedTaskId === FALSE) {
				$this->_conditionCode = self::VALUE_CONDITIONCODE_TASK_EVENT_ADD_ERROR;
				file_put_contents(dirname(__FILE__).'/../../../tclog.html', 'EE2:'.$name."<br />\n", FILE_APPEND);
				return FALSE;
			}
			/*** マップリストＤＥＬＥＴＥ＆ＩＮＳＥＲＴ */
			$this->_deleteTaskFromMapList($taskId);
			$this->_mapInfoText[] = $calendarId . ',' . $addedTaskId;
			/*** 更新中タスクＩＤ追加 */
			$this->_updatingTaskIdList[] = $addedTaskId;
		}
		$taskEvent = $event['task'][0];
		$uTimeTaskUpdated = $taskEvent[ToodledoConstants::KEY_MODIFIED];
		$uTimeTaskUpdated = strtotime($uTimeTaskUpdated) + 46800;
		$uTimeCalendarUpdated = strtotime((string)$calendarEvent[Google_Calender::KEY_EVENT_UPDATED]);
		/*** タスクの更新日時の方が新しい場合 */
		if ($uTimeCalendarUpdated < $uTimeTaskUpdated) {
			// 現状のままリターン
			return TRUE;
		}
		/*** Toodledoイベント更新 */
		$result = $this->updateTask($taskId, $name, $content, $startUTime, $startSTime, $length, $calendarEvent['ALLDAY']);
		/*** エラー判定 */
		if ($result === FALSE) {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_TASK_EVENT_UPDATE_ERROR;
			return FALSE;
		}
		/*** 更新中タスクＩＤ追加 */
		$this->_updatingTaskIdList[] = $taskId;

		$this->恒久的タスクURLを追加してカレンダーに書き戻す($taskId, $calendarEvent);

		return TRUE;
	}

	protected function 恒久的タスクURLを追加してカレンダーに書き戻す($taskId, $calendarEvent)
	{
	    $恒久的URL = self::恒久的URLを作成する($taskId);
	    $content = (string)$calendarEvent[Google_Calender::KEY_EVENT_CONTENT];
	    if (self::コンテンツに恒久的URLが含まれている場合TRUEを返す($content, $恒久的URL) == TRUE) {
	        return;
	    }
	    $content = self::コンテンツに恒久的URLを追加する($content, $恒久的URL);
	    $calendarId = (string)$calendarEvent[Google_Calender::KEY_EVENT_ID];
	    $name = (string)$calendarEvent[Google_Calender::KEY_EVENT_NAME];
	    $startUTime = $calendarEvent[Google_Calender::KEY_EVENT_START_TIME];
	    $endUTime = $calendarEvent[Google_Calender::KEY_EVENT_END_TIME];
	    $startTime =  Google_Calender::uTime2String($startUTime);
	    $endTime = Google_Calender::uTime2String($endUTime);
	    $this->updateCalendarEvent($calendarId, $name, $content, $startTime, $endTime);
	}

	/**
	 * タスク更新
	 * @param _Task $taskId
	 * @param _Task $name
	 * @param _Task $content
	 * @param _Task $startUTime
	 * @param _Task $startSTime
	 * @param _Task $length
	 * @param number $allDayFlg
	 * @return boolean
	 */
	public function updateTask($taskId, $name, $content, $startUTime, $startSTime, $length, $allDayFlg = 1)
	{
		$taskInfo = array(
				ToodledoConstants::KEY_ID => $taskId,
				ToodledoConstants::KEY_TITLE => $name,
				ToodledoConstants::KEY_NOTE => $content,
				ToodledoConstants::KEY_STARTDATE => $startUTime,
				ToodledoConstants::KEY_STARTTIME => $startSTime,
				ToodledoConstants::KEY_LENGTH => $length,
		);
		/*** 終日イベントの場合 */
		if ($allDayFlg == 0) {
			unset($taskInfo[ToodledoConstants::KEY_STARTTIME]);
			unset($taskInfo[ToodledoConstants::KEY_LENGTH]);
			$taskInfo[ToodledoConstants::KEY_STARTDATE] = date('Y-m-d', $startUTime);
		}
		$taskInfo[ToodledoConstants::KEY_STARTDATE] = date('Y-m-d', $startUTime);

		$result = $this->_Task->request(ToodledoConstants::METHOD_EDITTASK, $taskInfo, Toodledo::RAW);
		$sResult = Toodledo::xml2array($result);
		/*** エラー判定 */
		if (!is_numeric($sResult)) {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_TASK_EVENT_UPDATE_ERROR;
			return FALSE;
		}
		/** エラー判定 */
		if ($sResult != 1) {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_TASK_EVENT_UPDATE_ERROR;
			return FALSE;
		}
		return TRUE;
	}

	/**
	 * タスクにイベントを追加する
	 * @param _Task $name
	 * @param _Task $content
	 * @param _Task $startUTime
	 * @param _Task $startSTime
	 * @param _Task $length
	 * @param string $allDayFlg
	 * @return 追加したタスクのタスクＩＤ
	 */
	public function addTask($name, $content, $startUTime, $startSTime, $length, $allDayFlg=1)
	{
		$taskInfo = array(
				ToodledoConstants::KEY_TITLE => $name,
				ToodledoConstants::KEY_NOTE => $content,
				ToodledoConstants::KEY_STARTDATE => $startUTime,
				ToodledoConstants::KEY_STARTTIME => $startSTime,
				ToodledoConstants::KEY_LENGTH => $length,
		);
		/*** 終日イベントの場合 */
		if ($allDayFlg == 0) {
			unset($taskInfo[ToodledoConstants::KEY_STARTTIME]);
			unset($taskInfo[ToodledoConstants::KEY_LENGTH]);
			$taskInfo[ToodledoConstants::KEY_STARTDATE] = date('Y-m-d', $startUTime);
		}
		$taskInfo[ToodledoConstants::KEY_STARTDATE] = date('Y-m-d', $startUTime);
		$result = $this->_Task->request(ToodledoConstants::METHOD_ADDTASK, $taskInfo, Toodledo::RAW);
		$addedTaskId = Toodledo::xml2array($result);
		/*** エラー判定 */
		if (!is_numeric($addedTaskId)) {
			file_put_contents(dirname(__FILE__).'/../../../tclog.html', $result."<br />\n", FILE_APPEND);
			$this->_conditionCode = self::VALUE_CONDITIONCODE_TASK_EVENT_ADD_ERROR;
			return FALSE;
		}
		return $addedTaskId;
	}

	/**
	 * マップ情報を読み込む」
	 */
	protected function _loadMapInfo()
	{
		$this->_mapInfoText = array();
		$this->_pathEventMap = dirname(__FILE__) . '/eventmap/databox/mapinfo' .$this->_userHash. '.csv';
		/*** あれば読む */
		if (file_exists($this->_pathEventMap)) {
			$this->_mapInfoText = file($this->_pathEventMap,FILE_IGNORE_NEW_LINES|FILE_SKIP_EMPTY_LINES);
		}
	}

	/**
	 * マップ情報をカレンダーイベントIDをキーとする連想配列に変換する
	 */
	protected function _createMapInfoCalendarEventKeyHash() {
		$aryResult = array ();
		/*** マッピングイベントを全件処理する */
		foreach ( $this->_mapInfoText as $map ) {
			$divide = explode ( ',', $map );
			/*** フォーマット判定 */
			if (count ( $divide ) > 0) {
				$key = '';
				/*** フォーマット判定 */
				if (isset ( $divide [0] )) {
					$key = $divide [0];
				}
				$value = '';
				/*** フォーマット判定 */
				if (isset ( $divide [1] )) {
					$value = $divide [1];
				}
				$aryResultTemp = array (
						$key => $value
				);
				$aryResult = array_merge($aryResult,$aryResultTemp);
			}
		}
		return $aryResult;
	}

	/**
	 * マップ情報をタスクイベントIDをキーとする連想配列に変換する
	 */
	protected function _createMapInfoTaskEventKeyHash() {
		$aryResult = array ();
		/*** マップ情報全件処理する */
		foreach ( $this->_mapInfoText as $map ) {
			$divide = explode ( ',', $map );
			/** フォーマット判定 */
			if (count ( $divide ) > 0) {
				$key = '';
				/** フォーマット判定 */
				if (isset ( $divide [1] )) {
					$key = $divide [1];
				}
				$value = '';
				/** フォーマット判定 */
				if (isset ( $divide [0] )) {
					$value = $divide [0];
				}
				$aryResultTemp = array (
						(string)$key => $value
				);
				$aryResult = $aryResult + $aryResultTemp;
			}
		}
		return $aryResult;
	}

	/**
	 * 最終更新日以降に更新されたタスクイベント取得
	 * @param _Task $tUser
	 * @param _Task $tPass
	 * @param _Task $appId
	 * @param _Task $updatedMin
	 */
	protected function _setTaskEvents($tUser,$tPass,$appId, $updatedMin)
	{
		$this->_taskEventList = array();
		$ret = $this->_Task->request(ToodledoConstants::METHOD_GETTASKS, array('modafter'=>$updatedMin), Toodledo::RAW);
		/*** エラー判定 */
		if ($ret === FALSE) {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_TASK_EVENT_GET_EEROR;
			return FALSE;
		}
		$event = Toodledo::xml2array($ret);
		/*** ログインエラー判定 */
		if ($event === ToodledoConstants::VALUE_ERROR_LOGIN_ERROR) {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_LOGIN_ERRROR_TASK;
			return FALSE;
		}
		/*** イベント有り */
		if ($event['total'] > 0) {
			$this->_taskEventList = $event['task'];
		}

	}

	/**
	 * 最終同期日時以降のに更新されたカレンダーイベント取得
	 * @param _Task $cUser
	 * @param _Task $cPassword
	 * @param _Task $updatedMin
	 * @param string $calendarName
	 * @return boolean
	 */
	protected function _setCalendarEvents($cUser, $cPassword, $updatedMin, $calendarName = '')
	{
		/*** ユーザカレンダー名を設定する：存在しない場合はエラーリターン */
		if ($this->_Calendar->selectCalendarByName($calendarName) === FALSE) {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_NOCALENDATNAME;
			return FALSE;
		}
		/*** 指定日以降に更新されているイベントリストを取得する。  */
		$this->_calendarEventList = $this->_Calendar->getEventList($updatedMin);
		/*** エラーリターン判定 */
		if ($this->_calendarEventList === FALSE) {
			$errorMessage = $this->_Calendar->exceptionErrorMessage;
			$this->_conditionCode = self::VALUE_CONDITIONCODE_CALENDAR_EVENT_GET_ERROR;
			return FALSE;
		}
		return TRUE;
	}

	/**
	 * 最終同期日時を返す。
	 * 最終同期日時が保存されていない場合は、現在日時を返す。
	 */
	public function getLastModifyDatetime()
	{
		$this->_pathLastModifyDatetime = dirname(__FILE__).'/eventmap/databox/lastmodify' .$this->_userHash. '.txt';
		/** 最終同期日時保存ファイルが未生成の場合、現在日時を返す */
		if (!file_exists($this->_pathLastModifyDatetime)) {
			$this->_conditionCode = self::VALUE_CONDITIONCODE_DISIDE_SYNCDATETIME;
			$result = date('Y-m-dTH:i:s');
		} else {
			$result = file_get_contents($this->_pathLastModifyDatetime);
			$result = trim($result);
		}
		return $result;
	}

	/**
	 * 現在日時で最終同期日時を更新する
	 */
	public function saveLastModifyDatetime()
	{
		$now = date(DateTime::ATOM);
		file_put_contents($this->_pathLastModifyDatetime, $now);
	}

	/**
	 * タスクイベントリストを下越
	 * @return Ambigous <multitype:, unknown>
	 */
	public function getTodoEventList()
	{
		return $this->_taskEventList;
	}

	/**
	 * カレンダーイベント一覧を返す
	 * @return Ambigous <boolean, unknown, multitype:>
	 */
	public function getCalendarEventList()
	{
		return $this->_calendarEventList;
	}

	/**
	 * 下駄
	 * get_$name()というメソッドがあればそれを実行する
	 * @param  $name
	 * @return
	 */
	public function __get($name) {
		$method = 'get_' .  $name;
		/*** get_$name()が存在すれば実行 */
		if (method_exists ( $this, $method )) {
			return call_user_func ( array (
					&$this,
					$method
			) );
		} else {
			/*** 存在しなければPHPエラー */
			trigger_error( 'Property ' . $name . '  does not exist');
			return null;
		}
	}

	/**
	 * 状態コードを返す
	 * @return number
	 */
	public function get_conditionCode()
	{
		return $this->_conditionCode;
	}
}

/**
 * 単体テストコードブロック
 */
require_once 'simpletest/unit_tester.php';
require_once 'simpletest/reporter.php';
/**
 * 単体テストクラス
 * @author admin
 *
 */
class EventmapTest extends UnitTestCase
{
	/** カレンダーユーザ */
	protected $_cUser;
	/** カレンダーパスワード */
	protected $_cPassword;
	/** ユーザーカレンダー名 */
	protected $_calendarName;
	/** タスクユーザ */
	protected $_tUser;
	/** タスクパスワード */
	protected $_tPassword;
	/** タスクアプリケーションＩＤ */
	protected $_tAppId;

	/**
	 * (non-PHPdoc)
	 * @see SimpleTestCase::setUp()
	 */
	public function setUp()
	{
		$up = file(dirname(__FILE__). '/eventmap/passwordc.txt', FILE_IGNORE_NEW_LINES);
		$this->_cUser = $up[0];
		$this->_cPassword = $up[1];
		$this->_calendarName = $up[2];
		$aryPassword = file(dirname(__FILE__). '/eventmap/passwordt.txt', FILE_IGNORE_NEW_LINES);
		$this->_tUser = $aryPassword[0];
		$this->_tPassword = $aryPassword[1];
		$this->_tAppId = $aryPassword[2];
		$this->_tAppId = Models_EventmappController::getAppIdToodledo();
	}

	/**
	 * 単体テスト
	 */
	public function test1100()
	{
		$obj = new Models_EventmappController(
				$this->_cUser,
				$this->_cPassword,
				$this->_tUser,
				$this->_tPassword,
				$this->_calendarName,
				$this->_tAppId
		);
		print_r($obj->getTodoEventList());
		echo "~~~~\n";
		print_r($obj->getCalendarEventList());
	}
}